package com.lry.basic.algorithm.queue;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/7/15
 */
public class SafeQueue<T>{
    private int capacity=10;
    private int size,tail,head;
    private T[] queue;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();//容器不满，生产者
    private Condition notEmpty = lock.newCondition();//容器不空，消费者

    public SafeQueue(){
        queue = (T[]) new Object[capacity];
    }
    public SafeQueue(int capacity){
        this.capacity = capacity;
        queue = (T[]) new Object[capacity];
    }
    //生产者
    public boolean enqueue(T t){
        try {
            lock.lock();
            if(t==null)return false;
            if(size==capacity){//容器已满，不能生产，必须等待
                notFull.await();
            }
            //可以生产
            queue[tail]=t;
            ++size;
            tail = (tail+1)%capacity;
            //生产完毕 可以通知消费者消费了
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return true;
    }

    public T dequeue(){
        T t = null;
        try{
            lock.lock();
            if(size==0){//不可消费
                notEmpty.await();
            }
            //消费
             t = queue[head];
            --size;
            head = (head+1)%capacity;
            //消费完成通知生产者生产
            notFull.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return t;
    }
}
